import React, { useState, useMemo, useEffect, useCallback, memo } from "react";
import classnames from "classnames";
import PropTypes from "prop-types";
import "./index.css";

const CityItem = memo(({ name, onSelect }) => (
  <li className="city-li" onClick={() => onSelect(name)}>
    {name}
  </li>
));

CityItem.propTypes = {
  name: PropTypes.string.isRequired,
  onSelect: PropTypes.func.isRequired
};

const CitySection = memo(({ title, cities = [], onSelect }) => (
  <ul className="city-ul">
    <li className="city-li" data-cate={title}>
      {title}
    </li>
    {cities.map(city => (
      <CityItem key={city.name} name={city.name} onSelect={onSelect} />
    ))}
  </ul>
));

CitySection.propTypes = {
  title: PropTypes.string.isRequired,
  cities: PropTypes.array,
  onSelect: PropTypes.func.isRequired
};

const AlphaIndex = memo(({ alpha, onClick }) => (
  <i className="city-index-item" onClick={() => onClick(alpha)}>
    {alpha}
  </i>
));

AlphaIndex.propTypes = {
  alpha: PropTypes.string.isRequired,
  onClick: PropTypes.func.isRequired
};

const alphabet = Array.from(new Array(26), (ele, index) =>
  String.fromCharCode(65 + index)
);

const CityList = memo(({ sections, toAlpha, onSelect }) => (
  <div className="city-list">
    <div className="city-cate">
      {sections.map(section => (
        <CitySection
          key={section.title}
          title={section.title}
          cities={section.cities}
          onSelect={onSelect}
        />
      ))}
    </div>

    <div className="city-index">
      {alphabet.map(alpha => (
        <AlphaIndex key={alpha} alpha={alpha} onClick={toAlpha} />
      ))}
    </div>
  </div>
));

CityList.propTypes = {
  sections: PropTypes.array.isRequired,
  onSelect: PropTypes.func.isRequired,
  toAlpha: PropTypes.func.isRequired
};

const Suggest = memo(({ keywords, onSelect }) => {
  const [result, setResult] = useState([]);

  useEffect(() => {
    fetch("/api/search?key=" + encodeURIComponent(keywords))
      .then(res => res.json())
      .then(data => {
        const { result } = data;
        setResult(result);
      });
  }, [keywords]);

  const checkResult = useMemo(() => {
    if (!result.length) {
      return [{ display: keywords }];
    }

    return result;
  }, [result, keywords]);

  return (
    <div className="city-suggest">
      <ul className="city-suggest-ul">
        {checkResult.map(item => (
          <CityItem
            key={item.display}
            name={item.display}
            onSelect={onSelect}
          />
        ))}
      </ul>
    </div>
  );
});

Suggest.propTypes = {
  keywords: PropTypes.string.isRequired,
  onSelect: PropTypes.func.isRequired
};

const CitySelector = memo(props => {
  const { show, cityData, isLoading, onBack, fetchCityData, onSelect } = props;

  const [searchKey, setSearchKey] = useState("");

  const key = useMemo(() => searchKey.trim(), [searchKey]);

  useEffect(() => {
    if (!show || cityData || isLoading) return;

    fetchCityData();
  }, [show, cityData, isLoading, fetchCityData]);

  const toAlpha = useCallback(alpha => {
    document.querySelector(`[data-cate='${alpha}']`).scrollIntoView();
  }, []);

  const cityWrapper = () => {
    if (isLoading) return <div></div>;

    if (cityData) {
      return (
        <CityList
          sections={cityData.cityList}
          onSelect={onSelect}
          toAlpha={toAlpha}
        />
      );
    }
  };

  return (
    <div className={classnames("city-selector", { hidden: !show })}>
      <div className="city-search">
        <div className="search-back" onClick={() => onBack()}>
          <svg width="42" height="42">
            <polyline
              points="25,13 16,21 25,29"
              stroke="#fff"
              strokeWidth="2"
              fill="none"
            />
          </svg>
        </div>
        <div className="search-input-wrapper">
          <input
            type="text"
            value={searchKey}
            className="search-input"
            placeholder="城市、车站的中文或拼音"
            onChange={e => setSearchKey(e.target.value)}
          />
        </div>
        <i
          onClick={() => setSearchKey("")}
          className={classnames("search-clean", { hidden: key.length === 0 })}
        >
          &#xf063;
        </i>
      </div>

      {Boolean(key) && (
        <Suggest keywords={key} onSelect={key => onSelect(key)} />
      )}

      {cityWrapper()}
    </div>
  );
});

CitySelector.propTypes = {
  show: PropTypes.bool.isRequired,
  cityData: PropTypes.object,
  isLoading: PropTypes.bool.isRequired,
  onBack: PropTypes.func.isRequired,
  fetchCityData: PropTypes.func.isRequired,
  onSelect: PropTypes.func.isRequired
};

export default CitySelector;
